Date: Tue Mar 24 12:26:08 2020
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong
# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom
# * Phylum
# * Class
# * Order
# * Family
# * Genus
# * Species
options(stringsAsFactors = FALSE,
scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE,
# message = FALSE,
# warning = FALSE,
# error = FALSE)
# require(knitr)
# require(kableExtra)
# require(shiny)
require(phyloseq)
require(data.table)
require(ggplot2)
require(plotly)
require(DT)
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE
Introduction
C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.
This document examines results from the WT mice samples.
We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?
Data preprocessing
Raw Data
FastQ files were downloaded from Dr. Kumar’s DropBox. A total of 60 files (2 per sample, pair-ended) and 2 metadata files were downloaded.
Prune data
The OTUs were mapped to Bacteria (98.34%), Eukaryota (1.43%) and undefined (0.23%) kingdoms.
The total of 8,129 unique sequences were found. Out of those, 7,994 were mapped to bacterial genomes.
dim(ps_may2019@otu_table@.Data)
[1] 30 8129
# Remove OTU unmapped to Bacteria
ps0 <- subset_taxa(ps_may2019,
Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
[1] 30 7994
These belonged to 13 Phylum. 230 of the OTUs (or 2.88% of bacterial OTUs) could not be mapped to a Phyla and were removed from this analysis (with 7,764 OTUs left).
t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
"Number of OTUs",
"Percent of OTUs")
datatable(t2,
rownames = FALSE,
caption = "Number of Bacterial OTUs by Phylum",
class = "cell-border stripe",
options = list(search = FALSE,
pageLength = nrow(t2))) %>%
formatCurrency(columns = 2,
currency = "",
mark = ",",
digits = 0) %>%
formatPercentage(columns = 3,
digits = 2)
ps1 <- subset_taxa(ps0,
!is.na(Phylum))
dim(ps1@otu_table@.Data)
[1] 30 7764
OTU table (first 10 rows)
Total counts per sample (i.e. sequencing depth)
tmp <- copy(smpl)
tmp$WEEK <- factor(tmp$WEEK,
levels = c("week 0",
"week 1",
"week 4"),
labels = c("Week 0",
"Week 1",
"Week 4"))
tmp$TREATMENT <- factor(tmp$TREATMENT,
levels = c("Control",
"PEITC"),
labels = c("AIN93M",
"PEITC"))
p1 <- ggplot(tmp,
aes(x = SAMPLE_NAME,
y = Total,
group = TREATMENT,
fill = TREATMENT)) +
facet_wrap(~ WEEK,
scale = "free_x") +
geom_bar(stat = "identity",
color = "black") +
scale_x_discrete("") +
scale_y_continuous("Number of Reads") +
scale_fill_grey("Treatment",
start = 0.2,
end = 0.8,
na.value = "red",
aesthetics = "fill") +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.position = "top")
tiff(filename = "tmp/seq_depth_may2019.tiff",
height = 4,
width = 6,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
print(p1)
Richness (Alpha diversity)
Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.
ps0@sam_data$Diet_Week <- paste(samples$TREATMENT,
samples$WEEK,
sep = "_")
ps0@sam_data$ID <- substr(x = ps0@sam_data$SAMPLE_NAME,
start = 2,
stop = 3)
p1 <- plot_richness(ps0,
x = "Diet_Week",
measures = "Shannon") +
geom_line(aes(group = ID),
color = "black") +
geom_point(aes(fill = ID),
shape = 21,
size = 3,
color = "black") +
scale_x_discrete("") +
theme(axis.text.x = element_text(angle = 30,
hjust = 1,
vjust = 1))
ggplotly(p = p1,
tooltip = c("ID",
"value"))
p1 <- p1 + theme(legend.position = "none")
tiff(filename = "tmp/wt_shannon.tiff",
height = 4,
width = 5,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
tmp <- data.table(p1$data)
tmp[, delta := value[WEEK == "week 4"] -
value[WEEK == "week 0"],
by = ID]
tmp1 <- droplevels(unique(tmp[WEEK %in% c("week 0",
"week 4"),
c("value",
"WEEK",
"TREATMENT")]))
m1 <- lm(value ~ WEEK*TREATMENT,
data = tmp1)
print("Model1: Shannon's index by treatment and time")
anova(m1)
tmp2 <- droplevels(unique(tmp[WEEK == "week 0",
c("delta",
"value",
"TREATMENT")]))
m2 <- lm(delta ~ TREATMENT,
data = tmp2)
print("Model2: Shannon's index differences (Week 4 - Week 0) by treatment")
anova(m2)
m3 <- wilcox.test(delta ~ TREATMENT,
data = tmp2)
print("Model3: Wilcoxon test for Shannon's index differences (Week 4 - Week 0) by treatment")
m3
The results showed that in 4 out of 5 animals in the PEITC group diversity increased over the 4 weeks compared to the baseline. At the same time, only 2 out of 5 Control animals increased its microbial diversity in the same period of time. NOTE: there was no statistically significant difference between the treatment groups as well as over time (see results above).
Counts at Phylum level
Relative abundance (%) at Phylum level
Remove phyla with relative abundance of >= 1% in less than 10% of samples.
t1 <- data.table(Phylum = ra_p$Phylum,
`Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <- t1$`Number of Samples`/30
setorder(t1, -`Number of Samples`)
datatable(t1,
rownames = FALSE,
caption = "Taxonomic count table",
class = "cell-border stripe",
options = list(search = FALSE,
pageLength = nrow(t1))) %>%
formatPercentage(columns = 3,
digits = 1)
Hence, only 6 out of 13 Phyla were studied in this analysis: Actinobacteria, Bacteroidetes, Firmicutes, Proteobacteria, Tenericutes and Verrucomicrobia. Relative abundance at the next taxonomic level (Class) was, therefore, computed relative to the sum of these 6 Phyla.
7,628 OTUs, down from 7,764 OTUs in the previous table.
Relative Abundance in Samples at Different Taxonomic Ranks
1. Class
p0 <- ggplot(mu,
aes(x = Week,
y = x,
group = Treatment)) +
facet_wrap(~ Class,
scale = "free_y") +
geom_line() +
geom_point(aes(shape = Treatment,
color = Treatment),
size = 3,
alpha = 0.5) +
scale_x_discrete("") +
scale_y_continuous("Relative Abundance (%)") +
theme(legend.position = "top",
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/wt_class_over_time.tiff",
height = 5,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)
p1 <- ggplot(mu,
aes(x = x,
y = Class,
color = Treatment,
shape = Week)) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)") +
theme(legend.position = "top")
tiff(filename = "tmp/wt_class_ra.tiff",
height = 4,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
2. Order
p0 <- ggplot(mu,
aes(x = Week,
y = x,
group = Treatment)) +
facet_wrap(~ Order,
scale = "free_y") +
geom_line() +
geom_point(aes(shape = Treatment,
color = Treatment),
size = 5,
alpha = 0.5)
print(p0)
p1 <- ggplot(mu,
aes(x = x,
y = Order,
fill = Treatment,
shape = Week)) +
# facet_wrap(~ Sex, nrow = 1) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)")
ggplotly(p1)
LS0tCnRpdGxlOiAiTnJmMiBCTDYgV2lsZC1UeXBlIChXVCkgUEVJVEMgMTZTIE1pY3JvYmlvbWUgRGF0YSBWaXN1YWxpemF0aW9uIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9Cm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgIHNjaXBlbiA9IDk5OSkKCiMgIyBJbmNyZWFzZSBtbWVtb3J5IHNpemUgdG8gNjQgR2ItLS0tCiMgaW52aXNpYmxlKHV0aWxzOjptZW1vcnkubGltaXQoNjU1MzYpKQoKCiMgc3RyKGtuaXRyOjpvcHRzX2NodW5rJGdldCgpKQojICMgTk9URTogdGhlIGJlbG93IGRvZXMgbm90IHdvcmshCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgCiMgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAojICAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IEZBTFNFKQoKIyByZXF1aXJlKGtuaXRyKQojIHJlcXVpcmUoa2FibGVFeHRyYSkKIyByZXF1aXJlKHNoaW55KQoKcmVxdWlyZShwaHlsb3NlcSkKcmVxdWlyZShkYXRhLnRhYmxlKQpyZXF1aXJlKGdncGxvdDIpCnJlcXVpcmUocGxvdGx5KQpyZXF1aXJlKERUKQoKc291cmNlKCJzb3VyY2UvZnVuY3Rpb25zX21heTIwMTkuUiIpCgojIE9uIFdpbmRvd3Mgc2V0IG11bHRpdGhyZWFkPUZBTFNFLS0tLQptdCA8LSBUUlVFCmBgYAoKIyBJbnRyb2R1Y3Rpb24KQzU3QkwvNiB3aWxkLXR5cGUgKFdUKSBhbmQgTnJmLTIgZG91YmxlLWtub2NrLW91dCAoS08gLS8tKSBtaWNlIHdlcmUgZ2l2ZW4gMi13ZWVrIG1pY3JvYmlvbWUgc3RhYmlsaXphdGlvbiBwcm9jZXNzIHVzaW5nIEFJTjkzTSBkaWV0IGFuZCA4IG1vcmUgd2Vla3MgdG8gdHJlYXQgd2l0aCBlaXRoZXIgQUlOOTNNIG9yIEFJTjkzTSA1JSBQRUlUQyBkaWV0LiBGZWNhbCBzYW1wbGVzIHdlcmUgY29sbGVjdGVkIHdlZWtseSwgaW1tZWRpYXRlbHkgZnJvemVuIGluIGxpcXVpZCBuaXRyb2dlbiBhbmQgc3RvcmVkIGF0IC04MF5vXkMuIFNlcnVtLCBjZWNhbCwgY29sb24gZXBpdGhlbGlhbCBhbmQgd2hvbGUgY29sb24gdGlzc3VlcyBhdCB3ZWVrIDEwIHdlcmUgYWxzbyBjb2xsZWN0ZWQgZm9yIGZ1cnRoZXIgYW5hbHlzZXMuIEJhc2VsaW5lLCB3ZWVrIDEgYW5kIDQgZmVjYWwgc2FtcGxlcyB3ZXJlIHNlbGVjdGVkIGZvciAxNnMgclJOQSBzZXF1ZW5jaW5nLiAgCiAgClRoaXMgZG9jdW1lbnQgZXhhbWluZXMgcmVzdWx0cyBmcm9tIHRoZSBXVCBtaWNlIHNhbXBsZXMuICAKICAKV2Ugd2lsbCBhdHRhbXB0IHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczogIAoxLiBEaWQgbWljcm9iaW9tZSBjaGFuZ2Ugb3ZlciB0aW1lPyAgCjIuIFdhcyBtaWNyb2Jpb21lIGFmZmVjdGVkIGJ5IGRpZXQ/ICAKMy4gV2FzIHRoZXJlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBLTyBhbmQgV1Q/ICAKNC4gSWYgdGhlcmUgd2FzIGEgY2hhbmdlIGluIG1pY3JvYmlvbWUgY29tcG9zaXRpb24sIHdoYXQgZnVuY3Rpb25hbCBjaGFuZ2VzIGRpZCBpdCBjYXJyeT8gV2hhdCBhcmUgdGhlIGVzc2VudGlhbCBmdW5jdGlvbnMgb2YgdGhlIGJhY3RlcmlhIGFmZmVjdGVkIGJ5IHRoZSB0cmVhdG1lbnQgYW5kIGhvdyBjYW4gdGhpcyBiZSBzaG93biBpbiB2aXZvIChtZXRhYm9saXRlcywgaW5mbGFtbWF0aW9uIG1hcmtlcnMsIGV0Yy4pPwoKIyBEYXRhIHByZXByb2Nlc3NpbmcKIyMgUmF3IERhdGEgCkZhc3RRIGZpbGVzIHdlcmUgZG93bmxvYWRlZCBmcm9tIFtEci4gS3VtYXIncyBEcm9wQm94XShodHRwczovL3d3dy5kcm9wYm94LmNvbS9zaC9zbTl0aW5tMGY1cjZ5MXYvQUFEakdQUlJOaUlNN3pNU2ZBTkRrUWpGYT9kbD0wKS4gQSB0b3RhbCBvZiA2MCBmaWxlcyAoMiBwZXIgc2FtcGxlLCBwYWlyLWVuZGVkKSBhbmQgMiBtZXRhZGF0YSBmaWxlcyB3ZXJlIGRvd25sb2FkZWQuCgojIyBTY3JpcHQKVGhpcyBzY3JpcHQgKCoqKm5yZjJ1YmlvbWVfZGFkYTJfbWF5MjAxOV92MS5SbWQqKiopIHdhcyBkZXZlbG9wZWQgdXNpbmcgW0RBREEyIFBpcGVsaW5lIFR1dG9yaWFsICgxLjEyKV0oaHR0cHM6Ly9iZW5qam5lYi5naXRodWIuaW8vZGFkYTIvdHV0b3JpYWwuaHRtbCkgd2l0aCB0aXBzIGFuZCB0cmlja3MgZnJvbSB0aGUgW1VuaXZlcnNpdHkgb2YgTWFyeWxhbmQgU2hvb2wgb2YgTWVkaWNpbmUgSW5zdGl0dXRlIGZvciBHZW5vbWUgU2NpZW5jZXMgKElHUyldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvKSBbTWljcm9iaW9tZSBBbmFseXNpcyBXb3Jrc2hvcCAoQXByaWwgOC0xMSwgMjAxOSldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvZWR1Y2F0aW9uL3drc2hwX21ldGFnZW5vbWUucGhwKS4gVGhlIG91dHB1dCBvZiB0aGUgREFEQTIgc2NyaXB0ICgqKipkYXRhX21heTIwMTkvcHNfbWF5MjAxOS5SRGF0YSoqKikgaXMgZXhwbG9yZWQgaW4gdGhpcyBkb2N1bWVudC4KCiMgTWV0YSBkYXRhOiBzYW1wbGUgZGVzY3JpcHRpb24KYGBge3IgZGF0YX0KIyBMb2FkIGRhdGEtLS0tCiMgQ291bnRzCmxvYWQoImRhdGFfbWF5MjAxOS9wc19tYXkyMDE5LlJEYXRhIikKCiMgVGF4b25vbXkKbG9hZCgiZGF0YV9tYXkyMDE5L3RheGEuUkRhdGEiKQp0YXhhIDwtIGRhdGEudGFibGUoc2VxMTZzID0gcm93bmFtZXModGF4YSksCiAgICAgICAgICAgICAgICAgICB0YXhhKQoKIyBTYW1wbGVzCnNhbXBsZXMgPC0gcHNfbWF5MjAxOUBzYW1fZGF0YQpkYXRhdGFibGUoc2FtcGxlcywKICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gbnJvdyhzYW1wbGVzKSkpCmBgYAoKIyBQcnVuZSBkYXRhClRoZSBPVFVzIHdlcmUgbWFwcGVkIHRvIEJhY3RlcmlhICg5OC4zNCUpLCBFdWthcnlvdGEgKDEuNDMlKSBhbmQgdW5kZWZpbmVkICgwLjIzJSkga2luZ2RvbXMuIAoKYGBge3IgY2hlY2tfbWFwcGluZ19raW5nZG9tLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQp0MSA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19tYXkyMDE5KVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MSRWMVtpcy5uYSh0MSRWMSldIDwtICJVbmtub3duIgoKdDFbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQxLCAtTikKCmNvbG5hbWVzKHQxKSA8LSBjKCJLaW5nZG9tIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBPVFVzIGJ5IEtpbmdkb20iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDEpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKClRoZSB0b3RhbCBvZiA4LDEyOSB1bmlxdWUgc2VxdWVuY2VzIHdlcmUgZm91bmQuIE91dCBvZiB0aG9zZSwgNyw5OTQgd2VyZSBtYXBwZWQgdG8gYmFjdGVyaWFsIGdlbm9tZXMuIAoKYGBge3Iga2VlcF9iYWN0ZXJpYX0KZGltKHBzX21heTIwMTlAb3R1X3RhYmxlQC5EYXRhKQoKIyBSZW1vdmUgT1RVIHVubWFwcGVkIHRvIEJhY3RlcmlhCnBzMCA8LSBzdWJzZXRfdGF4YShwc19tYXkyMDE5LCAKICAgICAgICAgICAgICAgICAgIEtpbmdkb20gPT0gIkJhY3RlcmlhIikKZGltKHBzMEBvdHVfdGFibGVALkRhdGEpCmBgYAogIApUaGVzZSBiZWxvbmdlZCB0byAxMyBQaHlsdW0uIDIzMCBvZiB0aGUgT1RVcyAob3IgMi44OCUgb2YgYmFjdGVyaWFsIE9UVXMpIGNvdWxkIG5vdCBiZSBtYXBwZWQgdG8gYSBQaHlsYSBhbmQgd2VyZSByZW1vdmVkIGZyb20gdGhpcyBhbmFseXNpcyAod2l0aCA3LDc2NCBPVFVzIGxlZnQpLgoKYGBge3IgcGh5bHVtX21hcHBpbmd9CnQyIDwtIGRhdGEudGFibGUodGFibGUodGF4X3RhYmxlKHBzMClbLCAiUGh5bHVtIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQyJFYxW2lzLm5hKHQyJFYxKV0gPC0gIlVua25vd24iCnNldG9yZGVyKHQyLCAtTikKdDJbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQyLCAtTikKCmNvbG5hbWVzKHQyKSA8LSBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKCmRhdGF0YWJsZSh0MiwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBCYWN0ZXJpYWwgT1RVcyBieSBQaHlsdW0iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDIpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICAhaXMubmEoUGh5bHVtKSkKZGltKHBzMUBvdHVfdGFibGVALkRhdGEpCmBgYAoKIyBPVFUgdGFibGUgKGZpcnN0IDEwIHJvd3MpCmBgYHtyIG90dV90YWJsZSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9Cm90dSA8LSBkYXRhLnRhYmxlKHBzMEB0YXhfdGFibGVALkRhdGEsCiAgICAgICAgICAgICAgICAgIHQocHMwQG90dV90YWJsZUAuRGF0YSkpCmRhdGF0YWJsZShoZWFkKG90dSwgMTApLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gNzozNiwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgojIFRvdGFsIGNvdW50cyBwZXIgc2FtcGxlIChpLmUuIHNlcXVlbmNpbmcgZGVwdGgpCmBgYHtyIFRheCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9NX0KdDEgPC0gY29sU3VtcyhvdHVbLCA3Om5jb2wob3R1KV0pCnQxIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBuYW1lcyh0MSksCiAgICAgICAgICAgICAgICAgVG90YWwgPSB0MSkKCnRtcCA8LSBkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc2FtcGxlcyRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc2FtcGxlcyRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgIFdFRUsgPSBzYW1wbGVzJFdFRUspCgpzbXBsIDwtIG1lcmdlKHRtcCwKICAgICAgICAgICAgdDEsCiAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCnAxIDwtIGdncGxvdChzbXBsLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBXRUVLKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiU2FtcGxlIE5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJOdW1iZXIgb2YgUmVhZHMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgiR3JvdXAiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKSAKZ2dwbG90bHkocDEpCmBgYAoKYGBge3Igc2VxX2RlcHRoX2dyZXlzY2FsZSwgLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNH0KdG1wIDwtIGNvcHkoc21wbCkKdG1wJFdFRUsgPC0gZmFjdG9yKHRtcCRXRUVLLAogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndlZWsgMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZWVrIDQiKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJXZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldlZWsgMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayA0IikpCgp0bXAkVFJFQVRNRU5UIDwtIGZhY3Rvcih0bXAkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJDb250cm9sIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEVJVEMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQUlOOTNNIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEVJVEMiKSkKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFRvdGFsLAogICAgICAgICAgICAgICAgIGdyb3VwID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQpKSArCiAgZmFjZXRfd3JhcCh+IFdFRUssCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3giKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiTnVtYmVyIG9mIFJlYWRzIikgKwogIHNjYWxlX2ZpbGxfZ3JleSgiVHJlYXRtZW50IiwgCiAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMC4yLCAKICAgICAgICAgICAgICAgICAgZW5kID0gMC44LAogICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJyZWQiLAogICAgICAgICAgICAgICAgICBhZXN0aGV0aWNzID0gImZpbGwiKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvc2VxX2RlcHRoX21heTIwMTkudGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDEpCmBgYAoKIyBSaWNobmVzcyAoQWxwaGEgZGl2ZXJzaXR5KQpTaGFubm9uJ3MgZGl2ZXJzaXR5IGluZGV4IHdhcyBjYWxjdWxhdGVkIGZvciBlYWNoIHNhbXBsZSBhbmQgcGxvdGVkIG92ZXIgdGltZSB1c2luZyB0aGUgNyw3NjQgZnJvbSB0aGUgMTMgUGh5bHVtIGFib3ZlLgoKYGBge3IgcmljaG5lc3MsIGZpZy53aWR0aCA9IDEwLGZpZy5oZWlnaHQgPSA1fQpwczBAc2FtX2RhdGEkRGlldF9XZWVrIDwtIHBhc3RlKHNhbXBsZXMkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiXyIpCnBzMEBzYW1fZGF0YSRJRCA8LSBzdWJzdHIoeCA9IHBzMEBzYW1fZGF0YSRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcCA9IDMpCnAxIDwtIHBsb3RfcmljaG5lc3MocHMwLAogICAgICAgICAgICAgICAgICAgIHggPSAiRGlldF9XZWVrIiwgCiAgICAgICAgICAgICAgICAgICAgbWVhc3VyZXMgPSAiU2hhbm5vbiIpICsKICAgIGdlb21fbGluZShhZXMoZ3JvdXAgPSBJRCksCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBJRCksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxKSkKCmdncGxvdGx5KHAgPSBwMSwKICAgICAgICAgdG9vbHRpcCA9IGMoIklEIiwKICAgICAgICAgICAgICAgICAgICAgInZhbHVlIikpCgpwMSA8LSBwMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X3NoYW5ub24udGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDUsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQpgYGAKCmBgYHtyIHRlc3RfcmljaG5lc3N9CnRtcCA8LSBkYXRhLnRhYmxlKHAxJGRhdGEpCnRtcFssIGRlbHRhIDo9IHZhbHVlW1dFRUsgPT0gIndlZWsgNCJdIC0gCiAgICAgIHZhbHVlW1dFRUsgPT0gIndlZWsgMCJdLAogICAgYnkgPSBJRF0KCnRtcDEgPC0gZHJvcGxldmVscyh1bmlxdWUodG1wW1dFRUsgJWluJSBjKCJ3ZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlayA0IiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJ2YWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldFRUsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUUkVBVE1FTlQiKV0pKQptMSA8LSBsbSh2YWx1ZSB+IFdFRUsqVFJFQVRNRU5ULAogICAgICAgICBkYXRhID0gdG1wMSkKcHJpbnQoIk1vZGVsMTogU2hhbm5vbidzIGluZGV4IGJ5IHRyZWF0bWVudCBhbmQgdGltZSIpCmFub3ZhKG0xKQoKdG1wMiA8LSBkcm9wbGV2ZWxzKHVuaXF1ZSh0bXBbV0VFSyA9PSAid2VlayAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImRlbHRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidmFsdWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUUkVBVE1FTlQiKV0pKQptMiA8LSBsbShkZWx0YSB+IFRSRUFUTUVOVCwKICAgICAgICAgZGF0YSA9IHRtcDIpCnByaW50KCJNb2RlbDI6IFNoYW5ub24ncyBpbmRleCBkaWZmZXJlbmNlcyAoV2VlayA0IC0gV2VlayAwKSBieSB0cmVhdG1lbnQiKQphbm92YShtMikKCm0zIDwtIHdpbGNveC50ZXN0KGRlbHRhIH4gVFJFQVRNRU5ULAogICAgICAgICAgICBkYXRhID0gdG1wMikKcHJpbnQoIk1vZGVsMzogV2lsY294b24gdGVzdCBmb3IgU2hhbm5vbidzIGluZGV4IGRpZmZlcmVuY2VzIChXZWVrIDQgLSBXZWVrIDApIGJ5IHRyZWF0bWVudCIpCm0zCmBgYAogIApUaGUgcmVzdWx0cyBzaG93ZWQgdGhhdCBpbiA0IG91dCBvZiA1IGFuaW1hbHMgaW4gdGhlIFBFSVRDIGdyb3VwIGRpdmVyc2l0eSBpbmNyZWFzZWQgb3ZlciB0aGUgNCB3ZWVrcyBjb21wYXJlZCB0byB0aGUgYmFzZWxpbmUuIEF0IHRoZSBzYW1lIHRpbWUsIG9ubHkgMiBvdXQgb2YgNSBDb250cm9sIGFuaW1hbHMgaW5jcmVhc2VkIGl0cyBtaWNyb2JpYWwgZGl2ZXJzaXR5IGluIHRoZSBzYW1lIHBlcmlvZCBvZiB0aW1lLiBOT1RFOiB0aGVyZSB3YXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHRyZWF0bWVudCBncm91cHMgYXMgd2VsbCBhcyBvdmVyIHRpbWUgKHNlZSByZXN1bHRzIGFib3ZlKS4gIAogIAojIENvdW50cyBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgY291bnRzX3AsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpjb3VudHNfcCA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJQaHlsdW0iKQpzZXRvcmRlcihjb3VudHNfcCwgLWAwQTFgKQpkYXRhdGFibGUoY291bnRzX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KGNvdW50c19wKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgUmVsYXRpdmUgYWJ1bmRhbmNlICglKSBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgcmFfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnJhX3AgPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzID0gY291bnRzX3AsCiAgICAgICAgICAgICAgICAgICAgICAgcGN0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZGlnaXQgPSA0KQoKZGF0YXRhYmxlKHJhX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHJhX3ApKSkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKUmVtb3ZlIHBoeWxhIHdpdGggcmVsYXRpdmUgYWJ1bmRhbmNlIG9mID49IDElIGluIGxlc3MgdGhhbiAxMCUgb2Ygc2FtcGxlcy4KCmBgYHtyIHByZXZfcH0KdDEgPC0gZGF0YS50YWJsZShQaHlsdW0gPSByYV9wJFBoeWx1bSwKICAgICAgICAgICAgICAgICBgTnVtYmVyIG9mIFNhbXBsZXNgID0gcm93U3VtcyhyYV9wWywgMjpuY29sKHJhX3ApXSA+PSAwLjAxKSkKdDEkYFBlcmNlbnQgU2FtcGxlc2AgPC0gIHQxJGBOdW1iZXIgb2YgU2FtcGxlc2AvMzAKCnNldG9yZGVyKHQxLCAtYE51bWJlciBvZiBTYW1wbGVzYCkKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMSkKYGBgCgpIZW5jZSwgb25seSA2IG91dCBvZiAxMyBQaHlsYSB3ZXJlIHN0dWRpZWQgaW4gdGhpcyBhbmFseXNpczogQWN0aW5vYmFjdGVyaWEsIEJhY3Rlcm9pZGV0ZXMsIEZpcm1pY3V0ZXMsIFByb3Rlb2JhY3RlcmlhLCBUZW5lcmljdXRlcyBhbmQgVmVycnVjb21pY3JvYmlhLiBSZWxhdGl2ZSBhYnVuZGFuY2UgYXQgdGhlIG5leHQgdGF4b25vbWljIGxldmVsIChDbGFzcykgd2FzLCB0aGVyZWZvcmUsIGNvbXB1dGVkIHJlbGF0aXZlIHRvIHRoZSBzdW0gb2YgdGhlc2UgNiBQaHlsYS4KCmBgYHtyIGtlZXBfNl9waHlsYSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmtlZXBfcCA8LSB0MSRQaHlsdW1bdDEkYFBlcmNlbnQgU2FtcGxlc2AgPj0gMC4xXQpwYXN0ZTAoa2VlcF9wLCBjb2xsYXBzZSA9ICIsICIpCgpwczEgPC0gc3Vic2V0X3RheGEocHMwLCAKICAgICAgICAgICAgICAgICAgIFBoeWx1bSAlaW4lIGtlZXBfcCApCm90dTEgPC0gZGF0YS50YWJsZShwczFAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICAgdChwczFAb3R1X3RhYmxlQC5EYXRhKSkKCmRhdGF0YWJsZShoZWFkKG90dTEsIDEwKSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDc6bmNvbChvdHUxKSwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgo3LDYyOCBPVFVzLCBkb3duIGZyb20gNyw3NjQgT1RVcyBpbiB0aGUgcHJldmlvdXMgdGFibGUuCgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgaW4gU2FtcGxlcyBhdCBEaWZmZXJlbnQgVGF4b25vbWljIFJhbmtzCiMjIDEuIENsYXNzCmBgYHtyIGNvdW50c19jLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD02fQpjb3VudHNfYyA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiQ2xhc3MiKQpyYV9jIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19jKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2xhc3MiKV0pCgpyYV9jIDwtIG1lcmdlKHRheC5yYW5rcywKICAgICAgICAgICAgICByYV9jLAogICAgICAgICAgICAgIGJ5ID0gIkNsYXNzIikKCnRvdGFsIDwtIHJvd1N1bXMocmFfY1ssIDM6bmNvbChyYV9jKV0pCgpyYV9jJENsYXNzIDwtIGZhY3RvcihyYV9jJENsYXNzLAogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSByYV9jJENsYXNzW29yZGVyKHRvdGFsKV0pCgpyYV9jJFBoeWx1bSA8LSBmYWN0b3IocmFfYyRQaHlsdW0sCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmFfYyRQaHlsdW1bb3JkZXIodG90YWwpXSkpCnRtcCA8LSBtZWx0LmRhdGEudGFibGUoZGF0YSA9IHJhX2MsCiAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAzOm5jb2woY291bnRzX2MpLAogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiU0FNUExFX05BTUUiLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiUkEiKQoKdG1wIDwtIG1lcmdlKGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBzYW1wbGVzJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICBXRUVLID0gc2FtcGxlcyRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzYW1wbGVzJFRSRUFUTUVOVCksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IENsYXNzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5ULAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeCIsCiAgICAgICAgICAgICBucm93ID0gMykgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIG1lYW5zX2MsIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfYywKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNhbXBsZXMsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGFzcyA9IGxyYSRDbGFzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJDbGFzcyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkNsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRDbGFzcyA8LSBmYWN0b3IobXUkQ2xhc3MsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJENsYXNzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KG11KSwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkKYGBgCgoKYGBge3IgbWVhbnNfY19wMCwgZmlnLndpZHRoID0gNywgZmlnLmhlaWdodCA9IDV9CnAwIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRyZWF0bWVudCkpICsKICBmYWNldF93cmFwKH4gQ2xhc3MsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJlYXRtZW50KSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X2NsYXNzX292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA1LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgoKYGBge3IgbWVhbnNfY19wMSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDZ9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gQ2xhc3MsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfY2xhc3NfcmEudGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDEpCmBgYAoKIyMgMi4gT3JkZXIKYGBge3IgY291bnRzX28sIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD0xMCxmaWcuaGVpZ2h0PTZ9CmNvdW50c19vIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJPcmRlciIpCnJhX28gPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzX28pCgp0YXgucmFua3MgPC0gdW5pcXVlKG90dTFbLCBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPcmRlciIpXSkKCnJhX28gPC0gbWVyZ2UodGF4LnJhbmtzLAogICAgICAgICAgICAgIHJhX28sCiAgICAgICAgICAgICAgYnkgPSAiT3JkZXIiKQoKdG90YWwgPC0gcm93U3VtcyhyYV9vWywgMzpuY29sKHJhX28pXSkKCnJhX28kT3JkZXIgPC0gZmFjdG9yKHJhX28kT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHJhX28kT3JkZXJbb3JkZXIodG90YWwpXSkKCnJhX28kUGh5bHVtIDwtIGZhY3RvcihyYV9vJFBoeWx1bSwKICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShyYV9vJFBoeWx1bVtvcmRlcih0b3RhbCldKSkKdG1wIDwtIG1lbHQuZGF0YS50YWJsZShkYXRhID0gcmFfbywKICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IDM6bmNvbChjb3VudHNfbyksCiAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJTQU1QTEVfTkFNRSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJSQSIpCgp0bXAgPC0gbWVyZ2UoZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNhbXBsZXMkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgICAgICAgIFdFRUsgPSBzYW1wbGVzJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNhbXBsZXMkVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHRtcCwKICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgUGxvdCBzYW1wbGVzCnAxIDwtIGdncGxvdCh0bXAsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBSQSwKICAgICAgICAgICAgICAgICBmaWxsID0gT3JkZXIsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBQaHlsdW0pKSArCiAgZmFjZXRfd3JhcCh+IFdFRUsgKyBUUkVBVE1FTlQsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDEpCmBgYAoKYGBge3IgbWVhbnNfbywgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbHJhIDwtIHJhX21lbHQocmEgPSByYV9vLAogICAgICAgICAgICAgICBzYW1wbGVzID0gc2FtcGxlcywKICAgICAgICAgICAgICAgc2FtcGxlX25hbWUgPSAiU0FNUExFX05BTUUiKQoKbXUgPC0gZGF0YS50YWJsZShhZ2dyZWdhdGUobHJhJFJBLAogICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoV2VlayA9IGxyYSRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gbHJhJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9yZGVyID0gbHJhJE9yZGVyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSkKbXVbLCB0b3RhbCA6PSBzdW0oeCksCiAgIGJ5ID0gIk9yZGVyIl0KdWwgPC0gdW5pcXVlKG11WywgYygiT3JkZXIiLCAKICAgICAgICAgICAgICAgICAgICAidG90YWwiKV0pCnVsIDwtIHVsW29yZGVyKHRvdGFsKSxdCm11JE9yZGVyIDwtIGZhY3RvcihtdSRPcmRlciwKICAgICAgICAgICAgICAgICAgIGxldmVsID0gdWwkT3JkZXIpCm11JHRvdGFsIDwtIE5VTEwKCmRhdGF0YWJsZShtdSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3cobXUpLAogICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBsaXN0KGxpc3QoMywgJ2Rlc2MnKSkpKQpgYGAKCmBgYHtyIG1lYW5zX29fcDAsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KcDAgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSBXZWVrLAogICAgICAgICAgICAgICAgIHkgPSB4LAogICAgICAgICAgICAgICAgIGdyb3VwID0gVHJlYXRtZW50KSkgKwogIGZhY2V0X3dyYXAofiBPcmRlciwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcmVhdG1lbnQpLAogICAgICAgICAgICAgc2l6ZSA9IDUsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfb19wMSwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSAxMH0KcDEgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgIHkgPSBPcmRlciwKICAgICAgICAgICAgICAgICBmaWxsID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIHNoYXBlID0gV2VlaykpICsKICAjIGZhY2V0X3dyYXAofiBTZXgsIG5yb3cgPSAxKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwKICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKQpnZ3Bsb3RseShwMSkKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg